<?php
class ZendX_Sphinx_Request
{
    const MAX_ITEMS_RESULT = 5000;
    protected $_filters = array();
    protected $_default_index = 'products';
    protected $_offset = NULL;
    protected $_index = NULL;
    protected $_field = NULL;
    protected $_sort = array();
    protected $_attr = NULL;
    protected $_sign = NULL;
    protected $_search = '1';

    public function __construct($index = NULL, $field = NULL)
    {
        $this->_index = $index;
        $this->_field = $field;
    }

    /**
     * @param string $what or array if you want set like package
     * @param array $range
     * @return Utils_Sphinx_Request
     */
    public function whereIn($what, array $range = NULL)
    {
        if (is_array($what)) foreach ($what as $item) $this->whereIn($item[0], $item[1]);
        $this->_filters[] = array('what' => $what, 'range' => (array)$range);
        return $this;
    }

    /**
     * @param string $what
     * @param array $range
     * @return Utils_Sphinx_Request
     */
    public function whereIs($what, array $range = array())
    {
        foreach ($range as $id) {
            $this->_filters[] = array('what' => $what, 'range' => (array)$id);
        }
        return $this;
    }

    public function filter(array $filters)
    {
        foreach ($filters as $key => $val) {
            $this->whereIs($key, (array)$val);
        }
        return $this;
    }

    /**
     * @param int $offset
     * @param int $count
     * @return Utils_Sphinx_Request
     */
    public function offset($offset, $count)
    {
        $this->_offset = array('offset' => $offset, 'count' => $count);
        return $this;
    }

    /**
     * @param string $attr or array if you want set like package
     * @param bool $is_asc
     * @return Utils_Sphinx_Request
     */
    public function sortedBy($attr, $is_asc = true)
    {
        if (is_array($attr)) foreach ($attr as $item) $this->sortedBy($item[0], $item[1]);
        $this->_sort[] = array('attr' => $attr, 'type' => $is_asc ? 'ASC' : 'DESC');
        return $this;
    }

    public function search($content)
    {
        $this->_search = $content;
        return $this;
    }

    /**
     * @param Utils_Sphinx $client
     * @param bool $noLimit
     * @return void
     */
    public function apply(ZendX_Sphinx $client)
    {
        $client->resetFilters();
        foreach ($this->_filters as $filter) {
            $client->setFilter($filter['what'], $filter['range']);
        }

        if (NULL !== $this->_offset)
            $client->setLimits((int)$this->_offset['offset'], (int)$this->_offset['count'], self::MAX_ITEMS_RESULT); else
            $client->setLimits(0, self::MAX_ITEMS_RESULT, self::MAX_ITEMS_RESULT);

        $sort_part = array();
        foreach ($this->_sort as $value) $sort_part[] = implode(' ', $value);

        if (!empty($sort_part))
            $client->SetSortMode(SPH_SORT_EXTENDED, implode(', ', $sort_part));

    }

    public function getSign()
    {
        if (NULL === $this->_sign) {
            $result = array();
            foreach ($this->_filters as $filter) {
                $result[0][$filter['what']] = $filter['range'];
            }

            if (NULL !== $this->_offset) {
                $result[1][(int)$this->_offset['offset']] = (int)$this->_offset['count'];
            } else {
                $result[1][0] = self::MAX_ITEMS_RESULT;
            }

            $sort_part = array();
            foreach ($this->_sort as $value) $sort_part[] = implode(' ', $value);
            $result[2] = implode(', ', $sort_part);
            $result[3] = $this->getSearchIndex();
            $result[4] = $this->getSearchContent();
            $this->_sign = sha1(json_encode($result));
        }
        return $this->_sign;
    }

    /**
     * getter for index
     * @return string
     */
    public function getIndex()
    {
        return $this->_index;
    }

    /**
     * @return Utils_Param_Container
     */
    public function getAttr()
    {
        return $this->_attr;
    }

    /**
     * @return string
     */
    public function getSearchIndex()
    {
        return (NULL !== $this->_index) ? $this->_index : $this->_default_index;
    }

    public function getSearchContent()
    {
        $str = '';
        if (NULL !== $this->_field) {
            $str = "@{$this->_field} ";
        }
        return $str . "{$this->_search}";
    }
}
